package main

import (
	"fmt"
	"reflect"
)

func ReflectValueAndElem() {
	i := 3
	// typ1 := reflect.TypeOf(i)
	val1 := reflect.ValueOf(i)
	// typ2 := reflect.TypeOf(&i)
	val2 := reflect.ValueOf(&i)

	fmt.Println("i_val:", val1.CanSet())              // false
	fmt.Println("&i_val:", val2.CanSet())             // false
	fmt.Println("&i_elem_val:", val2.Elem().CanSet()) // true
	// 可以看到，val2.Elem() 与 val1 的意义相等，但是在反射的视角上，两者又是不同
	// val1 是通过valueOf获取得到，int在valueOf的时候，是通过一级指针*int构造出了reflect.value对象。【return Value{t, e.word, f} ， t为*int, e.word为具体的int值指针，f为指针】
	// val2: val2在valueOf的时候，传入的是*int，所以是通过**int构造了reflect.Value对象。【return Value{t, e.word, f} ， t为**int ， e.word为*int ，f为指针】
	// 两个value操作的都是指针类型，指针类型是不可改变的
	// val.Elem(): 通过val2这个reflect.value进行Elem操作，会构造一个新对象【return Value{typ, ptr, fl} ， t为**int ，ptr为*int ，f发生了改变计算fl := v.flag&flagRO | flagIndir | flagAddr。fl |= flag(typ.Kind()) 】
	// flag标识的重新计算导致了reflect.value对象变成了可变的。
}
